home *** CD-ROM | disk | FTP | other *** search
- /*++
- /* NAME
- /* gpres.c 3
- /* SUMMARY
- /* g-protocol general interface
- /* PROJECT
- /* pc-mail
- /* PACKAGE
- /* cico
- /* SYNOPSIS
- /* int gopen(fd);
- /* int fd;
- /*
- /* int gwrite(fd,buf,len)
- /* int fd,len;
- /* char *buf;
- /*
- /* int gread(fd,buf,len)
- /* int fd,len;
- /* char *buf;
- /*
- /* int gclose(fd)
- /* int fd;
- /* DESCRIPTION
- /* The functions in this module present an interface that closely
- /* resembles the unix kernel i/o interface.
- /*
- /* gopen() handles the initial message exchange. fd should be
- /* connected to a tty line. gopen() normally returns a zero value.
- /*
- /* gwrite() returns the number of bytes `written' to the remote system.
- /* It should be considered an error if this is not equal to the number
- /* of bytes requested.
- /* A zero-length write should be used to indicate EOF during file transfer.
- /*
- /* gread() returns the requested number of bytes or the number of
- /* bytes sent by the remote system, whichever is smaller.
- /* A zero-length read indicates EOF during file transfer.
- /*
- /* gclose() shuts the protocol down, but does not otherwise change
- /* communications line parameters. It normally returns a zero value.
- /* FUNCTIONS AND MACROS
- /* galloc(), gfree(), gsproto(), grproto()
- /* DIAGNOSTICS
- /* All functions return -1 in case of unrecoverable problems.
- /* BUGS
- /* All g protocol routines assume that the XON/XOFF flow control
- /* has been turned off.
- /* Some parts of the code rely on 8-bit bytes, 16-bit short integers.
- /* AUTHOR(S)
- /* W.Z. Venema
- /* Eindhoven University of Technology
- /* Department of Mathematics and Computer Science
- /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- /* CREATION DATE
- /* Sun Apr 19 12:41:37 GMT+1:00 1987
- /* LAST MODIFICATION
- /* 90/01/22 13:01:43
- /* VERSION/RELEASE
- /* 2.1
- /*--*/
-
- #include <setjmp.h>
- #include "gp.h"
-
- /* local and forward declarations */
-
- static jmp_buf failbuf;
- static void gpeek(),gpoke(),memcpy();
-
- /* gfail - exception handling */
-
- void gfail()
- {
- longjmp(failbuf,1);
- }
-
- /* gopen - not quite an analogon of unix open(2) */
-
- int gopen(fd)
- int fd;
- {
- return(ginit(fd)); /* do packet stuff elsewhere */
- }
-
- /* gwrite - g-protocol analogon of unix write(2) */
-
- gwrite(fd,data,len)
- int fd,len;
- char *data;
- {
- /* set up exception handling */
-
- if (setjmp(failbuf)) /* in case gsproto fails */
- return(FAIL); /* it just did */
-
- /* handle special case of zero-length writes separately */
-
- if (len <= 0) { /* end-of-file message */
- register Packet *pk = galloc(); /* allocate output packet */
- gpoke(pk,data,len); /* make null-data packet */
- gsproto(fd,pk); /* send to other side */
- } else { /* true data message */
- register int shot; /* quantum size */
- register int rest; /* amount left to do */
- for (rest = len; rest > 0; rest -= shot,data += shot) {
- register Packet *pk = galloc(); /* allocate output packet */
- gpoke(pk,data,shot = MIN(pk->len,rest));/* fill the packet */
- gsproto(fd,pk);
- }
- }
- return(len); /* no problems detected */
- }
-
- /* gread - g-protocol analogon of unix read(2) */
-
- gread(fd,data,len)
- int fd,len;
- char *data;
- {
- static Packet *pk; /* our byte stock */
- register int igot; /* our return value */
-
- /* set up exception handling */
-
- if (setjmp(failbuf)) /* in case grproto fails */
- return(FAIL); /* it just did */
-
- /* if no bytes in stock, get some fresh ones and see how much we got */
-
- if (pk == 0 || pk->segl <= 0) /* we are out of data */
- gpeek(pk = grproto(fd)); /* get fresh packet */
-
- /* return as many bytes as asked, or as in stock, whichever is less */
-
- if ((igot = MIN(len,pk->segl)) > 0) {
- memcpy(data,pk->segp,igot); /* copy to caller's buffer */
- pk->segp += igot; /* update stock pointer */
- pk->segl -= igot; /* update stock count */
- }
- if (pk->segl <= 0) /* if we exhausted the stock */
- gfree(pk); /* release packet */
- return(igot); /* no problems detected */
- }
-
- /* gclose - turn g protocol off */
-
- gclose(fd)
- int fd;
- {
- return(gfinit(fd)); /* not here! */
- }
-
- /*
- * "Each transmitter is constrained to observe the maximum data segment"
- * "size established during initial synchronization by the receiver that"
- * "it sends to. (...) `short' packets have zero or more data bytes but less"
- * "than the maximum. The first one or two bytes of the data segment of"
- * "a short packet are `count' bytes that indicate the difference between"
- * "the maximum size and the number of bytes in the short segment. If the"
- * "difference is less than 127, one count byte is used. If the difference"
- * "exceeds 127, then the low-order seven bits of the difference are put"
- * "in the first data byte and the remaining high-order bit is set as an"
- * "indication that the remaining bits of the difference are in the second"
- * "byte.
- */
-
- /* gpoke - prepare packet for transmission */
-
- static void gpoke(pk,data,len)
- register Packet *pk;
- int len;
- char *data;
- {
- register int diff = pk->len-len; /* packet/data size mismatch */
-
- pk->segp = pk->data; /* set up write pointer */
- pk->segl = len; /* actual segment length */
- if (diff < 0 || len < 0) {
- DEBUG(7,"gpoke: trouble\n",""); /* something very wrong */
- gfail();
- /* NOTREACHED */
- } else if (diff == 0) {
- pk->c = DATA; /* long data segment */
- } else if (diff <= 127) {
- pk->c = SHORT; /* short data segment */
- *pk->segp++ = diff; /* one difference byte */
- } else if (diff > 127) {
- pk->c = SHORT; /* tiny data segment */
- *pk->segp++ = diff|0200; /* two difference bytes */
- *pk->segp++ = diff>>7;
- }
- memcpy(pk->segp,data,pk->segl); /* copy data into packet */
- }
-
- /* gpeek - prepare newly packet for reading */
-
- static void gpeek(pk)
- register Packet *pk;
- {
- register int diff;
-
- pk->segp = pk->data; /* set up read pointer */
- if (TYPE(pk->c) == DATA) {
- diff = 0; /* long data segment */
- } else if (TYPE(pk->c) != SHORT) {
- DEBUG(7,"gread: trouble\n",""); /* something funny */
- gfail();
- /* NOTREACHED */
- } else if ((diff = *pk->segp++&0377)&0200) {/* short data segment */
- diff = (diff&0177)|((*pk->segp++&0377)<<7);
- }
- pk->segl = pk->len-diff; /* actual segment size */
- DEBUG(9,"rcv: data %d bytes\n",pk->segl);
- }
-
- /* memcpy - not-so-efficient implementation */
-
- static void memcpy(dst,src,len)
- register char *dst,*src;
- register int len;
- {
- while (len-- > 0)
- *dst++ = *src++;
- }
-